/*
 * spi_driver.c
 *
 *  Created on: 2021��5��27��
 *      Author: Administrator
 */
#include "spi_driver.h"
#include "xspi.h"
#include "xparameters.h"


#define SPI_DEVICE_ID		XPAR_SPI_1_DEVICE_ID
static XSpi  SpiInstance;

int XSpi_init()
{
	int Status;
	XSpi_Config *ConfigPtr;	/* Pointer to Configuration data */

	ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
	if (ConfigPtr == NULL) {
		return XST_DEVICE_NOT_FOUND;
	}

	XSpi *SpiInstancePtr = &SpiInstance;

	Status = XSpi_CfgInitialize(SpiInstancePtr, ConfigPtr,
				  ConfigPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to ensure that the hardware was built correctly.
	 */
	Status = XSpi_SelfTest(SpiInstancePtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Run loopback test only in case of standard SPI mode.
	 */
	if (SpiInstancePtr->SpiMode != XSP_STANDARD_MODE) {
		return XST_SUCCESS;
	}

	/*
	 * Set the Spi device as a master and in loopback mode.
	 */
	Status = XSpi_SetOptions(SpiInstancePtr, XSP_MASTER_OPTION);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Start the SPI driver so that the device is enabled.
	 */
	XSpi_Start(SpiInstancePtr);

	/*
	 * Disable Global interrupt to use polled mode operation
	 */
	XSpi_IntrGlobalDisable(SpiInstancePtr);


	return XST_SUCCESS;
}

int xSpi_trans(u32 slavedev_sel_bit, u8 *writeBufPtr, u8 *readBufPtr, u32 byte_num){
	XSpi *SpiInstancePtr = &SpiInstance;
	int status = XSpi_SetSlaveSelect(SpiInstancePtr, slavedev_sel_bit);
	if(status != 0){
		return status;
	}
	// gw_print("SlaveSelectReg : 0x%x  , SlaveSelectMask : 0x%x\r\n", SpiInstancePtr->SlaveSelectReg, SpiInstancePtr->SlaveSelectMask);
	status = XSpi_Transfer(SpiInstancePtr, writeBufPtr, readBufPtr, byte_num);
	return status;
}



/*
 * Function name:   spi_trans(base_addr,slavedev_sel_bit,writeBufPtr,readBufPtr,byte_num)
 * Paramter :       base_addr: AXI quad spi IPcore base addrress
 * 					slavedev_sel_bit: chose slave device,default FF,only one bit low is choosed
 * 					writeBufPtr: wr {cmd,addr,data} to fifo,it is array,it name is pointer ofwriteBufPtr[0]
 * 					readBufPtr :the same
 * 					byte_num : the trans data bit / 8bit = byte_num
 */
//use for CPOL =0;CPHA =0;cdcm,

void spi_trans(u32 base_addr, u32 slavedev_sel_bit, u8 *writeBufPtr, u8 *readBufPtr, u32 byte_num, u8 CPHA_OL )
{
	u8 cmd = *writeBufPtr;
	u32 i,statereg;

	XSpi_WriteReg(base_addr, XSP_SRR_OFFSET, 0xA);//reset
	XSpi_WriteReg(base_addr, XSP_DGIER_OFFSET, 0X80000000);//31bit-1,enab_intrupt
	XSpi_WriteReg(base_addr, XSP_IIER_OFFSET, 0x4);//open the(SPI DTR)empty interpt
	if(CPHA_OL == 0){//HA_OL=0 0
		//disable trans
		XSpi_WriteReg(base_addr, XSP_CR_OFFSET, 0X1E6);//000(1).1110.0110/(1)is dis_tran reset RX/TX FIFO
		XSpi_WriteReg(base_addr, XSP_CR_OFFSET, 0X186);//000(1).1000.0110/(1)is dis_tran
		//Write cmd&addr&data to fifo
		for(i=0; i<byte_num;i = i+1 )
		{
			XSpi_WriteReg(base_addr, XSP_DTR_OFFSET, *writeBufPtr);//trans to data trans reg
			writeBufPtr = writeBufPtr + 1;
		}
		//choose slave_dev and trans
		XSpi_WriteReg(base_addr, XSP_SSR_OFFSET, slavedev_sel_bit);//choose slave_dev, active low
		XSpi_WriteReg(base_addr, XSP_CR_OFFSET, 0X086);//000(0).1(00)0.0110//start trans
		//wait for trans to be done
		do{ statereg = XSpi_ReadReg(base_addr, XSP_SR_OFFSET); }
		while((statereg & XSP_SR_TX_EMPTY_MASK)== 0);
		//stop trans
		XSpi_WriteReg(base_addr, XSP_IISR_OFFSET, 0X4);//clear (SPI  DTR)is empty mask bit
		XSpi_WriteReg(base_addr, XSP_SSR_OFFSET, 0XFFFF);//disconnect slave_dev
		XSpi_WriteReg(base_addr, XSP_CR_OFFSET, 0X186);//000(1).1000.0110//control 1 disab_tran

		if((cmd & 0x80) != 0x80){
			return;
		}

		//read data
		for(i=0; i<byte_num;i = i+1 )
		{
			*readBufPtr = (u8)XSpi_ReadReg(base_addr, XSP_DRR_OFFSET);
			readBufPtr = readBufPtr + 1;
			if((XSpi_ReadReg(base_addr, XSP_SR_OFFSET) & XSP_SR_RX_EMPTY_MASK) == 1){
				break;
			}
		}
	}
}


